PER-8985 feat: Playwright drop-in baseline seeding — build attributes + exec orchestration - #2335
PER-8985 feat: Playwright drop-in baseline seeding — build attributes + exec orchestration#2335Shivanshu-07 wants to merge 20 commits into
Conversation
…orchestration - @percy/client createBuild: allow-listed drop-in build sources via PERCY_BUILD_SOURCE, plus dropin-baseline-candidate / dropin-baseline-setup attributes (env or explicit options) the API keys baseline auto-approval on. - @percy/cli-exec: generic baseline-provider discovery (any installed SDK package can declare "@percy/cli".baselineProvider). On an empty project, percy exec uploads the committed baseline screenshots as an auto-approved build #1 before the user's command runs; established projects get a notice pointing at the SDK's explicit setup command. Seeding helpers exported for SDK-contributed commands. - @percy/core: expose the server-decided build source on percy.build so SDKs can key on it through the healthcheck. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Verified E2E against a local percy-api: a web project's snapshot create requires a root resource, so raw-PNG comparison tiles are rejected. Seed uploads now use client.sendSnapshot with the same generated root-DOM + image-resource shape 'percy upload' uses for web projects — Percy renders the baseline in the project's own browsers, so it pairs with the head run's DOM snapshots by (name, browser, width). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Seeding dispatches by project type: web projects seed rendered snapshots (root DOM + image resource); app projects seed raw comparison uploads (tag + tile), exactly how App Percy ingests screenshots. Exec seeding now engages for app tokens too. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The same env var the SDK override honors — one switch turns off both the toHaveScreenshot override and exec's baseline provider discovery. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- core: only set percy.build.source when the API returned one — an own 'source: undefined' key survives in-process but drops out of JSON responses, breaking the API-server shape specs. - cli-exec: cover the exec seeding block (real provider-package fixture) and the remaining baseline.js branches for the 100% coverage gate. - cli-exec: sanitize dirent names / paths at the fs boundary in the provider walk (also clears semgrep's path-join-resolve-traversal findings on the diff). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Direct sanitizer unit tests, walk fixtures for every discovery skip branch (empty dir, ESM named-export provider without discoverBaselines), and the non-web/app token exec branch; istanbul-ignore the two defense-in-depth dirent guards unreachable via readdir. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The seed build keeps rendering and only auto-approves once it reaches finished; head snapshots select their baseline as they process, so starting the head immediately raced the approval and a lost race made the whole first run report as new instead of diffing. Poll the seed build up to the pipeline latency budget (10m) with a 30s heartbeat, degrade to a warning instead of blocking on timeout or status errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pin-baseline # Conflicts: # packages/client/src/client.js # packages/client/test/client.test.js
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Master-inherited coverage gap from the metadata-SSRF change — the catch path for a colon-containing host that fails URL parsing was never exercised, holding @percy/core under the 100% gate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every caller (matchMetadataHost) null-guards before calling, so the branch cannot be exercised by tests; it held @percy/core under the 100% gate on master too. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The seed upload omitted browserName, so seed and head comparisons landed on different canonical tag rows and screenshot pairing missed — the first app run diffed nothing. One tag shape, defined by the SDK. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- discovery walk now mirrors @percy/cli's findModulePackages exactly: stop at the nearest node_modules, never cross the home directory, and degrade to [] on any filesystem error — a throw here previously escaped to exec's outer catch and disabled Percy for the whole run - provider modules are confined to their declaring package (a baselineProvider path escaping the package root is skipped) - only ever seed build #1: an API that predates the candidate attribute hands back a normal build, which previously seeded stray baseline builds into established projects on every run - falsy provider baseline entries are filtered instead of silently terminating an upload worker Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… idiom) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude Code PR ReviewPR: #2335 • Head: 0a38a90 • Reviewers: fallback inline checklist (deep-review agent) SummaryCLI-side drop-in baseline seeding: generic Review Table
FindingsAll review findings were fixed on this PR before this report:
Verdict: PASS |
…pin-baseline # Conflicts: # packages/core/src/utils.js
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tice An all-uploads-failed seed previously finalized an EMPTY auto-approved build #1, establishing the project with a blank baseline and permanently disabling the auto-seed path. Zero uploads now skip finalize (the unfinalized build expires server-side) and point at setup-baseline. Also: the established-project notice is one line instead of two, and a failed status poll reports 'state: unknown' instead of 'undefined'. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ower walk - exec drives maybeSeedBaseline through yieldTo so the up-to-10min seed wait stays tick-responsive to Ctrl-C (it was the one multi-minute stretch the abort signal couldn't unwind) - the zero-seed warning no longer promises that a plain re-run recovers (an unfinalized candidate build can bump the build number past the compat guard) — setup-baseline is the recovery path - unscoped walk collection narrowed from percy-* to percy-cli-*, matching findModulePackages exactly - env-fallback test added for the setup attribute Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude Code PR ReviewPR: #2335 • Head: da65d31 • Reviewers: fallback inline checklist (deep-review agent, re-review) SummaryRe-review after the master merge, reviewer-feedback fixes (zero-upload seed no longer finalizes), and comment cleanup. CLI-side drop-in baseline seeding: provider discovery, seed build #1 from committed screenshots with a bounded wait before the head build, allow-listed build sources, and the Review Table
FindingsRe-review findings (2 Medium, 3 Low), all fixed on this PR in da65d31:
Earlier human-review threads (aryanku-dev): all resolved — write-token wait verified empirically on staging; zero-upload finalize fixed; established-project notice reduced to one line. Verdict: PASS |
What
CLI-side support for the
@percy/playwrighttoHaveScreenshot drop-in's baseline flow:createBuildaccepts allow-listed drop-in build sources viaPERCY_BUILD_SOURCE(playwright-dropin/playwright-dropin-baseline) plusdropin-baseline-candidate/dropin-baseline-setupattributes (env or explicit options). The API keys baseline auto-approval on these."@percy/cli": { "baselineProvider": "..." }(no framework code enters the CLI, same scaling model as command discovery). On an EMPTY project,percy execuploads the committed baseline screenshots as an auto-approved build ⬆️ Bump @babel/register from 7.10.4 to 7.10.5 #1 before the user's command runs (the suite never executes for the baseline), then starts the head build. Established projects get a notice pointing at the SDK's explicitplaywright:setup-baselinecommand — the API's no-build-persisted sentinel guarantees no stray builds. Seeding dispatches by project type: web → rendered web snapshots (root DOM + image resource, thepercy uploadshape); app → comparison ingest (tag + tile, no render).sourceis kept onpercy.buildso SDKs can key on it through the healthcheck.Depends on
Testing
Client + exec suites green incl. 11 new seeding specs; E2E verified against a local percy-api and on staging (empty web/app seed → head diff flow, established-project sentinel, explicit setup command).
Deploy ordering
percy-api (percy/percy-api#6527) must ship first. Against an API that predates the
dropin-baseline-candidateattribute, the compat guard abandons the seed build unused — on an established project that leaves one stray unfinalized build per run until the API side is live (they expire server-side, but numbering inflates).🤖 Generated with Claude Code